package com.linkhub.oms.admin.modules.logistic.service.impl;

import com.linkhub.oms.admin.common.exception.ExceptionFactory;
import com.linkhub.oms.admin.modules.logistic.domain.param.BaseSingleChannelPriorityParam;
import com.linkhub.oms.admin.modules.logistic.domain.param.LogisticPriorityEditParam;
import com.linkhub.oms.admin.modules.logistic.domain.param.LogisticPriorityQueryParam;
import com.linkhub.oms.admin.modules.logistic.domain.param.ShippingNameAndChannelPriorityParam;
import com.linkhub.oms.admin.modules.logistic.domain.vo.ChannelPriorityVO;
import com.linkhub.oms.admin.modules.logistic.service.ChannelPriorityBizService;
import com.linkhub.oms.common.util.CacheKeyAssist;
import com.linkhub.oms.common.util.QtStreamUtil;
import com.linkhub.oms.component.redis.locker.DistributedLocker;
import com.linkhub.oms.dao.mpservice.IChannelPriorityService;
import com.linkhub.oms.entity.resulttype.ShopShippingChannelPriorityEntity;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author Jaycle
 * @version 1.0.0
 * @Description ChannelPriorityServiceImpl.java
 * @createTime 2024/05/03 15:19
 */
@Slf4j
@Service
public class ChannelPriorityBizServiceImpl implements ChannelPriorityBizService {

    @Resource
    private IChannelPriorityService channelPriorityService;

    @Resource
    private DistributedLocker distributedLocker;

    /**
     * 查询物流渠道优先级接口
     *
     * @param logisticPriorityQueryParam logisticPriorityQueryParam
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ChannelPriorityVO> queryChannelPriority(LogisticPriorityQueryParam logisticPriorityQueryParam) {
        String userId = logisticPriorityQueryParam.getUserId();
        // 查询用户所有的商店以及商店的运费名称、运费名称下面设置的物流渠道优先级
        List<ShopShippingChannelPriorityEntity> shopShippingChannelPriorityEntityList = channelPriorityService.queryShopByUserID(userId);
        // 转换为所需返回的结果形式
        List<ChannelPriorityVO> orderProducts = QtStreamUtil.map(shopShippingChannelPriorityEntityList,
                entity -> {
                    ChannelPriorityVO channelPriorityVO = new ChannelPriorityVO();
                    channelPriorityVO.setSysShopId(entity.getSysShopId());
                    channelPriorityVO.setShopName(entity.getShopName());

                    // 构建 ShippingNameAndChannelPriorityParam 列表
                    List<ShippingNameAndChannelPriorityParam> shippingNameAndChannelPriorityParamList = new ArrayList<>();
                    ShippingNameAndChannelPriorityParam shippingNameAndChannelPriorityParam = new ShippingNameAndChannelPriorityParam();
                    shippingNameAndChannelPriorityParam.setShippingName(entity.getShippingName());
                    shippingNameAndChannelPriorityParam.setChannelPriority(new ArrayList<>());

                    // 构建 BaseSingleChannelPriorityParam 列表
                    BaseSingleChannelPriorityParam baseSingleChannelPriorityParam = new BaseSingleChannelPriorityParam();
                    baseSingleChannelPriorityParam.setChannelCode(entity.getChannelCode());
                    baseSingleChannelPriorityParam.setPriority(entity.getRanked());
                    baseSingleChannelPriorityParam.setChannelEName(entity.getChannelEName());
                    baseSingleChannelPriorityParam.setChannelCName(entity.getChannelCName());
                    if (StringUtil.isNotBlank(entity.getChannelCode())) {
                        shippingNameAndChannelPriorityParam.getChannelPriority().add(baseSingleChannelPriorityParam);
                    }
                    if (StringUtil.isNotBlank(entity.getShippingName())) {
                        // 将 ShippingNameAndChannelPriorityParam 添加到列表中
                        shippingNameAndChannelPriorityParamList.add(shippingNameAndChannelPriorityParam);
                    }

                    // 设置 ChannelPriorityVO 的 shippingNameAndChannelPriorityParamList
                    channelPriorityVO.setShippingNameAndChannelPriorityParamList(shippingNameAndChannelPriorityParamList);

                    return channelPriorityVO;
                });
        // 整合同一商店、同一个运费名称的信息并按照商店ID、运费名称、优先级升序排序
        List<ChannelPriorityVO> result = integrateAndSort(orderProducts);
        return result;
    }

    /**
     * 编辑物流渠道优先级接口
     *
     * @param logisticPriorityEditParam logisticPriorityEditParam
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setChannelPriority(LogisticPriorityEditParam logisticPriorityEditParam) {
        String sysShopId = logisticPriorityEditParam.getSysShopId();
        String shippingName = logisticPriorityEditParam.getShippingName();
        // 加锁
        String lockKey = CacheKeyAssist.getChannelPriorityEditLockKey(sysShopId, shippingName);
        if (!distributedLocker.tryLock(lockKey)) {
            throw ExceptionFactory.getI18nBizException("logistic.channel.priority.edit.problem");
        }
        try {
            // 删除该商店该运费名称现有渠道优先级
            channelPriorityService.deleteChannelPriorityByShopIDAndShippingName(sysShopId, shippingName);
            List<String> channelCodeList = logisticPriorityEditParam.getChannelCodeList();
            int i = 1;
            for (String channelCode : channelCodeList) {
                Integer priority = Integer.valueOf(i);
                // 插入新的渠道优先级
                channelPriorityService.insertChannelPriorityByShopIDAndShippingName(sysShopId, shippingName, channelCode, priority);
                i++;
            }
        } finally {
            distributedLocker.unlock(lockKey);
        }
    }

    public List<ChannelPriorityVO> integrateAndSort(List<ChannelPriorityVO> channelPriorityVOList) {
        // 将数据按照sysShopId进行分组
        Map<String, List<ChannelPriorityVO>> shopIdMap = new HashMap<>();
        for (ChannelPriorityVO channelPriorityVO : channelPriorityVOList) {
            shopIdMap.computeIfAbsent(channelPriorityVO.getSysShopId(), k -> new ArrayList<>()).add(channelPriorityVO);
        }

        // 整合并排序每个sysShopId下的数据
        List<ChannelPriorityVO> result = new ArrayList<>();
        for (Map.Entry<String, List<ChannelPriorityVO>> entry : shopIdMap.entrySet()) {
            List<ChannelPriorityVO> shopIdGroup = entry.getValue();
            Map<String, Map<String, List<BaseSingleChannelPriorityParam>>> shippingNameMap = new HashMap<>();
            for (ChannelPriorityVO vo : shopIdGroup) {
                for (ShippingNameAndChannelPriorityParam shippingParam : vo.getShippingNameAndChannelPriorityParamList()) {
                    shippingNameMap.computeIfAbsent(shippingParam.getShippingName(), k -> new HashMap<>())
                            .merge(vo.getSysShopId(), shippingParam.getChannelPriority(),
                                    (list1, list2) -> {
                                        list1.addAll(list2);
                                        return list1;
                                    });
                }
            }

            List<ShippingNameAndChannelPriorityParam> sortedShippingParams = new ArrayList<>();
            for (Map.Entry<String, Map<String, List<BaseSingleChannelPriorityParam>>> shippingEntry : shippingNameMap.entrySet()) {
                List<BaseSingleChannelPriorityParam> channelPriorities = new ArrayList<>();
                for (Map.Entry<String, List<BaseSingleChannelPriorityParam>> channelEntry : shippingEntry.getValue().entrySet()) {
                    channelPriorities.addAll(channelEntry.getValue());
                }
                channelPriorities.sort(Comparator.comparingInt(BaseSingleChannelPriorityParam::getPriority));
                sortedShippingParams.add(new ShippingNameAndChannelPriorityParam(shippingEntry.getKey(), channelPriorities));
            }
            sortedShippingParams.sort(Comparator.comparing(ShippingNameAndChannelPriorityParam::getShippingName));

            result.add(new ChannelPriorityVO(entry.getKey(), shopIdGroup.get(0).getShopName(), sortedShippingParams));
        }

        // 对整合后的结果按照sysShopId、shippingName、priority升序排序
        result.sort(Comparator.comparing(ChannelPriorityVO::getSysShopId)
                .thenComparing((o1, o2) -> {
                    for (int i = 0; i < Math.min(o1.getShippingNameAndChannelPriorityParamList().size(), o2.getShippingNameAndChannelPriorityParamList().size()); i++) {
                        int compareResult = o1.getShippingNameAndChannelPriorityParamList().get(i).getShippingName()
                                .compareTo(o2.getShippingNameAndChannelPriorityParamList().get(i).getShippingName());
                        if (compareResult != 0) {
                            return compareResult;
                        }
                    }
                    return 0;
                })
                .thenComparing((o1, o2) -> {
                    for (int i = 0; i < Math.min(o1.getShippingNameAndChannelPriorityParamList().size(), o2.getShippingNameAndChannelPriorityParamList().size()); i++) {
                        List<BaseSingleChannelPriorityParam> priorityList1 = o1.getShippingNameAndChannelPriorityParamList().get(i).getChannelPriority();
                        List<BaseSingleChannelPriorityParam> priorityList2 = o2.getShippingNameAndChannelPriorityParamList().get(i).getChannelPriority();
                        for (int j = 0; j < Math.min(priorityList1.size(), priorityList2.size()); j++) {
                            int compareResult = priorityList1.get(j).getPriority().compareTo(priorityList2.get(j).getPriority());
                            if (compareResult != 0) {
                                return compareResult;
                            }
                        }
                    }
                    return 0;
                }));

        return result;
    }
}
